package com.qwq.service.impl;

import com.qwq.dto.GameRecordInputDto;
import com.qwq.dto.GameRecordOutputDto;
import com.qwq.dto.RankedInfoOutputDto;
import com.qwq.dto.SummonerInfoOutputDto;
import com.qwq.dto.gameData.AllGameDataResponse;
import com.qwq.dto.lcu.*;
import com.qwq.infrastructure.exception.StringResponseException;
import com.qwq.service.AppService;
import com.qwq.service.AsyncService;
import com.qwq.service.GameDataService;
import com.qwq.service.LcuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 程序主要功能，利用lcuApi实现一些自定义功能,给网页使用
 */
@Service
public class AppServiceImpl implements AppService {
    private final LcuService _lcuService;
    private final Logger _logger = LoggerFactory.getLogger(AppServiceImpl.class);
    private final AsyncService _asyncService;
    private final GameDataService _gameDataService;

    @Autowired
    public AppServiceImpl(LcuService lcuService, AsyncService asyncService, GameDataService gameDataService) {
        _lcuService = lcuService;
        _asyncService = asyncService;
        _gameDataService = gameDataService;
    }

    /**
     * 获取当前登陆游戏召唤师所有信息
     */
    public SummonerInfoOutputDto getCurrentSummonerInfo() {
        LolSummonerInfoResponse summonerInfoResponse = _lcuService.getLoginSummonerInfo();
        SummonerInfoOutputDto outputDto = new SummonerInfoOutputDto();
        outputDto.setName(summonerInfoResponse.getDisplayName());
        outputDto.setPuuid(summonerInfoResponse.getPuuid());
        outputDto.setLevel(summonerInfoResponse.getSummonerLevel());
        outputDto.setPrivacy(summonerInfoResponse.getPrivacy());
        outputDto.setProfileIconId(summonerInfoResponse.getProfileIconId());
        //获取蓝色精粹
        LolBlueEssenceResponse currentLolBlueEssenceResponse = _lcuService.getCurrentLolBlueEssenceResponse();
        outputDto.setBlueEssence(currentLolBlueEssenceResponse.getLolBlueEssence());
        //获取当前登陆大区
        ReportingEnvironmentResponse environmentResponse = _lcuService.getRiotclientV1CrashReportingEnvironment();
        outputDto.setArea(getArea(environmentResponse.getEnvironment()));
        //段位
        LolRankedV1RankedStatsResponse rankedInfoResponse = _lcuService.getRankedInfo(summonerInfoResponse.getPuuid());
        var rankedSoloDto = rankedInfoResponse.getQueues().stream()
                .filter(x -> "RANKED_SOLO_5x5".equalsIgnoreCase(x.getQueueType())).findFirst().get();
        outputDto.setRankedSolo(setRankedInfo(rankedSoloDto));
        var rankedLingHuoDto = rankedInfoResponse.getQueues().stream()
                .filter(x -> "RANKED_FLEX_SR".equalsIgnoreCase(x.getQueueType())).findFirst().get();
        outputDto.setRankedLingHuo(setRankedInfo(rankedLingHuoDto));
        return outputDto;
    }

    private RankedInfoOutputDto setRankedInfo(LolRankedV1RankedStatsResponse.QueuesDto rankedDto) {
        RankedInfoOutputDto rankedInfo = new RankedInfoOutputDto();
        if (!"NONE".equalsIgnoreCase(rankedDto.getTier())) {
            if (rankedDto.getDivision().equalsIgnoreCase("NA") || !StringUtils.hasText(rankedDto.getDivision())) {
                rankedInfo.setRank(rankConvert(rankedDto.getTier()));
            } else {
                rankedInfo.setRank(rankConvert(rankedDto.getTier()) + rankedDto.getDivision());
            }
            rankedInfo.setWin(rankedDto.getWins());
            rankedInfo.setPoint(rankedDto.getLeaguePoints());
        } else {
            rankedInfo.setRank(rankConvert(rankedDto.getTier()));
        }
        return rankedInfo;
    }

    private String rankConvert(String tier) {
        String result = null;
        switch (tier.toUpperCase()) {
            case "NONE":
                result = "未完成定位赛";
                break;
            case "IRON":
                result = "坚韧黑铁";
                break;
            case "BRONZE":
                result = "英勇黄铜";
                break;
            case "SILVER":
                result = "不屈白银";
                break;
            case "GOLD":
                result = "荣耀黄金";
                break;
            case "PLATINUM":
                result = "华贵铂金";
                break;
            case "DIAMOND":
                result = "璀璨钻石";
                break;
            case "MASTER":
                result = "超凡大师";
                break;
            case "GRANDMASTER":
                result = "傲世宗师";
                break;
            case "CHALLENGER":
                result = "最强王者";
                break;
        }
        return result;
    }

    /**
     * 获取大区名称
     *
     * @param areaCode 大区代码
     */
    public String getArea(String areaCode) {
        areaCode = areaCode.toLowerCase();
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(areaCode);
        int codeNumber = 0;
        if (matcher.find()) {
            codeNumber = Integer.parseInt(matcher.group(0));
        } else {
            return null;
        }
        // 电信
        if (areaCode.startsWith("hn")) {
            List<String> area = List.of("艾欧尼亚", "祖安", "诺克萨斯", "班德尔城", "皮尔特沃夫", "战争学院", "巨神峰", "雷瑟守备", "裁决之地", "黑色玫瑰", "暗影岛", "钢铁烈阳", "水晶之痕", "均衡教派", "影流", "守望之海", "征服之海", "卡拉曼达", "皮城警备");
            return area.get(codeNumber - 1);
        } else if (areaCode.startsWith("wt")) {
            List<String> area = List.of("比尔吉沃特", "德玛西亚", "弗雷尔卓德", "无畏先锋", "恕瑞玛", "扭曲丛林", "巨龙之巢");
            return area.get(codeNumber - 1);
        } else if (areaCode.startsWith("edu")) {
            List<String> area = List.of("教育网专区");
            return area.get(codeNumber - 1);
        } else if (areaCode.startsWith("bgp")) {
            List<String> area = List.of("男爵领域", "峡谷之巅");
            return area.get(codeNumber - 1);
        } else {
            return null;
        }
    }

    /**
     * 游戏战绩记录分析
     */
    public List<GameRecordOutputDto> GameRecordAnalyse(GameRecordInputDto inputDto) {
        if (inputDto.getLevelList() == null || inputDto.getLevelList().size() == 0) {
            inputDto.setLevelList(new ArrayList<>(List.of("牛马", "下等马", "中等马", "上等马", "小代")));
        }
        List<GameRecordOutputDto> outputDtoList = new ArrayList<>();
        List<LolSummonerInfoResponse> summonerInfoList = new ArrayList<>();
        // 选英雄房间id
        String roomName = null;
        // 游戏中分析敌方队伍战绩
        if (inputDto.isInGame()) {
            AllGameDataResponse allGameDataResponse = _gameDataService.getAllGameData();
            if (allGameDataResponse == null || allGameDataResponse.getAllPlayers() == null || allGameDataResponse.getAllPlayers().size() != 10) {
                throw new StringResponseException("获取敌方战绩失败");
            }
            if (allGameDataResponse.getActivePlayer() == null || !StringUtils.hasText(allGameDataResponse.getActivePlayer().getSummonerName())) {
                throw new StringResponseException("获取当前客户端玩家数据失败");
            }
            String activeSummonerName = allGameDataResponse.getActivePlayer().getSummonerName();
            AllGameDataResponse.AllPlayersDto activeSummoner = allGameDataResponse.getAllPlayers().stream().filter(x -> activeSummonerName.equals(x.getSummonerName())).findFirst().get();
            List<String> otherTeamSummonerName = allGameDataResponse.getAllPlayers().stream().filter(x -> !activeSummoner.getTeam().equals(x.getTeam())).map(x -> x.getSummonerName()).collect(Collectors.toList());
            if (otherTeamSummonerName.size() != 5) {
                throw new StringResponseException("敌方队伍人数不是5个");
            }
            for (String name : otherTeamSummonerName) {
                try {
                    LolSummonerInfoResponse summonerInfo = _lcuService.getSummonerInfoByName(name);
                    if (summonerInfo == null) {
                        throw new StringResponseException("召唤师信息查询失败");
                    }
                    summonerInfoList.add(summonerInfo);
                } catch (Exception e) {
                    _logger.error("获取队友召唤师信息异常,召唤师名字:{},异常,{}", name, e.getMessage());
                }

            }
        }
        // 选英雄时分析我方队伍战绩
        else {
            LolChampSelectV1SessionResponse roomInfo = _lcuService.getRoomInfo();
            if (roomInfo == null) {
                throw new StringResponseException("获取房间信息失败");
            }
            roomName = roomInfo.getChatDetails().getChatRoomName().split("@")[0];
            if (!StringUtils.hasText(roomName)) {
                throw new StringResponseException("获取房间名字失败");
            }
            // 房间聊天框记录信息
            List<LolChatConversationsRoomNameMessageResponse> roomMessageInfo = _lcuService.getMessagesByRoomName(roomName);
            if (roomMessageInfo == null || roomMessageInfo.size() == 0) {
                throw new StringResponseException("获取房间聊天信息失败");
            }
            List<String> roomSummonerIds = roomMessageInfo.stream()
                    .filter(x -> "joined_room".equalsIgnoreCase(x.getBody()) && "system".equalsIgnoreCase(x.getType()))
                    .filter(x -> x.getFromSummonerId() != null)
                    .map(x -> String.valueOf(x.getFromSummonerId()))
                    .distinct()
                    .collect(Collectors.toList());
            if (roomSummonerIds.size() == 0) {
                throw new StringResponseException("获取房间内队伍召唤师id失败");
            }
            for (String summonerId : roomSummonerIds) {
                try {
                    LolSummonerInfoResponse summonerInfo = _lcuService.getSummonerInfo(summonerId);
                    if (summonerInfo == null) {
                        throw new StringResponseException("召唤师信息查询失败");
                    }
                    summonerInfoList.add(summonerInfo);
                } catch (Exception e) {
                    _logger.error("获取队友召唤师信息异常,summonerId:{},异常,{}", summonerId, e.getMessage());
                }
            }
        }
        if (summonerInfoList.size() == 0) {
            throw new StringResponseException("未能查询到战绩");
        }
        //战绩分析
        for (var summonerInfo : summonerInfoList) {
            try {
                outputDtoList.add(summonerGameRecordAnalyse(summonerInfo));
            } catch (Exception e) {
                _logger.error("分析队友战绩summonerId:{},异常,{}", summonerInfo.getSummonerId(), e.getMessage());
            }
        }
        // 评价分析
        // 升序排列
        outputDtoList = outputDtoList.stream().sorted(Comparator.comparing(GameRecordOutputDto::getAvgKda)).collect(Collectors.toList());
        for (int i = 0; i < outputDtoList.size(); i++) {
            String assessment = inputDto.getLevelList().get(i);
            outputDtoList.get(i).setAssessment(assessment);
        }

        // 发送消息
        if (inputDto.isSendToTeammate()) {
            if (!inputDto.isInGame()) {
                _asyncService.sendToTeammate(outputDtoList, roomName);
            }
        }
        return outputDtoList;
    }

    /**
     * 游戏战绩详情分析
     *
     * @param summonerInfo
     * @return
     */
    private GameRecordOutputDto summonerGameRecordAnalyse(LolSummonerInfoResponse summonerInfo) {
        GameRecordOutputDto outputDto = new GameRecordOutputDto();
        outputDto.setSummonerName(summonerInfo.getDisplayName());
        outputDto.setSummonerId(summonerInfo.getSummonerId());
        // 段位查询
        LolRankedV1RankedStatsResponse rankedInfoResponse = _lcuService.getRankedInfo(summonerInfo.getPuuid());
        if (rankedInfoResponse == null) {
            throw new StringResponseException("段位查询失败");
        }
        var rankedSoloDto = rankedInfoResponse.getQueues().stream()
                .filter(x -> "RANKED_SOLO_5x5".equalsIgnoreCase(x.getQueueType())).findFirst().get();
        outputDto.setRankedSolo(setRankedInfo(rankedSoloDto));
        var rankedLingHuoDto = rankedInfoResponse.getQueues().stream()
                .filter(x -> "RANKED_FLEX_SR".equalsIgnoreCase(x.getQueueType())).findFirst().get();
        outputDto.setRankedLingHuo(setRankedInfo(rankedLingHuoDto));
        // 战绩查询
        LolMatchHistoryResponse matchHistoryInfo = _lcuService.getMatchHistoryInfo(summonerInfo.getPuuid(), 0, 6);
        if (matchHistoryInfo == null) {
            throw new StringResponseException("战绩查询失败");
        }
        List<LolMatchHistoryResponse.GamesDto.GameDetailsDto> gameDetails = matchHistoryInfo.getGames().getGamesDetails();
        if (gameDetails == null || gameDetails.size() == 0) {
            throw new StringResponseException("战绩记录为null或0");
        }
        List<GameRecordOutputDto.GameDetail> gameDetailDto = gameDetails.stream().map(x -> {
            GameRecordOutputDto.GameDetail gameDetail = new GameRecordOutputDto.GameDetail();
            gameDetail.setStartTime(new Date(x.getGameCreation()));
            LolMatchHistoryResponse.GamesDto.GameDetailsDto.ParticipantsDto participantsDto = x.getParticipants().get(0);
            LolMatchHistoryResponse.GamesDto.GameDetailsDto.ParticipantsDto.StatsDto stats = participantsDto.getStats();
            gameDetail.setChampionId(participantsDto.getChampionId());
            gameDetail.setAssist(stats.getAssists());
            gameDetail.setDeath(stats.getDeaths());
            gameDetail.setKill(stats.getKills());
            ChampionInfoResponse championInfo = _lcuService.getChampionInfo(gameDetail.getChampionId());
            if (championInfo == null) {
                throw new StringResponseException("获取英雄信息失败");
            }
            gameDetail.setChampionName(championInfo.getTitle());
            return gameDetail;
        }).sorted((o1, o2) -> o2.getStartTime().compareTo(o1.getStartTime())).collect(Collectors.toList());
        outputDto.setGameDetails(gameDetailDto);
        double avgKda = calculateAvgKda(outputDto.getGameDetails());
        outputDto.setAvgKda(avgKda);
        return outputDto;
    }


    /**
     * 计算平均kda
     *
     * @param list 战绩信息
     * @return 平均kda
     */
    private double calculateAvgKda(List<GameRecordOutputDto.GameDetail> list) {
        if (list.size() == 0) {
            return 0;
        }
        double total = 0;
        for (GameRecordOutputDto.GameDetail gameDetail : list) {
            Integer kill = gameDetail.getKill();
            Integer death = gameDetail.getDeath();
            Integer assist = gameDetail.getAssist();
            if (death == 0) {
                death = 1;
            }
            // kda计算 （击杀 + 助攻） / 死亡
            double kda = (kill * 1.0 + assist * 1.0) / (death * 1.0);
            total += kda;
        }
        DecimalFormat format = new DecimalFormat("#.00");

        return Double.parseDouble(format.format(total / list.size()));
    }
}
